/*
 * Copyright (c) 2011-2014, fortiss GmbH.
 * Licensed under the Apache License, Version 2.0.
 *
 * Use, modification and distribution are subject to the terms specified
 * in the accompanying license file LICENSE.txt located at the root directory
 * of this software distribution. A copy is available at
 * http://chromosome.fortiss.org/.
 *
 * This file is part of CHROMOSOME.
 *
 * $Id: componentRepository.h 7844 2014-03-14 14:11:49Z ruiz $
 */

/**
 * \file
 *         Component Repository.
 */

/**
 * \defgroup core_compRepository Component Repository group
 * @{
 *
 * \brief The component repository stores information about component instances.
 *
 * \details The level of information for component instances from local and foreign
 *          nodes is different.
 *          Instance-specific information about a component's ports and functions
 *          (e.g. data packet IDs for ports) are only available for local component
 *          instances.
 *
 *          Information about foreign component instances is only available
 *          when the Plug and Play Manager is located on this node, as the
 *          Plug and Play Manager is the only component who adds this kind of
 *          information.
 *
 *          Component instances may only be added here via the Plug and Play Manager
 *          or Plug and Play Client, or via code generated by the CHROMOSOME
 *          Modeling Tool (XMT). The latter only happens once before startup of
 *          a node.
 *
 *          Type specific information is not stored here (e.g. the type of a port).
 *          For this refer to the manifest of a component, stored in the manifest
 *          repository.
 *
 *          This is a mandatory core component, required on each CHROMOSOME node.
 */

// TODO (Issue #4307): What will happen when requesting unavailable info about foreign instances (e.g. dataPacket ID?)

// TODO (Issue #4308): The generated IDs should be used here (portTypeID). Currently these are in the component wrapper.
//                     Perhaps we should generate a header per component type with all kinds of IDs (componentType, portIDs, funcIDs).
//                     For functions we do not have any generated IDs at all.

#ifndef XME_CORE_NODEMGR_COMPONENTREPOSITORY_H
#define XME_CORE_NODEMGR_COMPONENTREPOSITORY_H

/******************************************************************************/
/***   Includes                                                             ***/
/******************************************************************************/
#include "xme/defines.h"

#include "xme/core/manifestTypes.h"
#include "xme/core/node.h"

/******************************************************************************/
/***   Defines                                                              ***/
/******************************************************************************/
#define XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE 0u ///< Denotes invalid handle for components, ports and functions.

/******************************************************************************/
/***   Type definitions                                                     ***/
/******************************************************************************/
/**
 * \typedef xme_core_nodeMgr_compRep_componentHandle_t
 *
 * \brief Component handle which identifies a component instance entry in the
 *        component repository.
 *        An invalid handle is denoted by XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE.
 */
typedef uint32_t
xme_core_nodeMgr_compRep_componentHandle_t;

/**
 * \typedef xme_core_nodeMgr_compRep_portHandle_t
 *
 * \brief Port handle which identifies an entry for the port of a component
 *        instance in the component repository.
 *        An invalid handle is denoted by XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE.
 */
typedef uint32_t
xme_core_nodeMgr_compRep_portHandle_t;

/**
 * \typedef xme_core_nodeMgr_compRep_functionHandle_t
 *
 * \brief Function handle which identifies an entry for the function of a
 *        component instance in the component repository.
 *        An invalid handle is denoted by XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE.
 */
typedef uint32_t
xme_core_nodeMgr_compRep_functionHandle_t;

/**
 * \enum xme_core_nodeMgr_compRep_state_e
 *
 * \brief Values for xme_core_nodeMgr_compRep_state_t.
 */
enum xme_core_nodeMgr_compRep_state_e
{
    XME_CORE_NODEMGR_COMPREP_STATE_INVALID = 0, ///< Components never have this state, this is used to indicate an error in the corresponding getter.
    XME_CORE_NODEMGR_COMPREP_STATE_PREPARED = 1, ///< Component is built, but not yet announced to the plug and play client or manager.
    XME_CORE_NODEMGR_COMPREP_STATE_ANNOUNCED = 2, ///< Component is announced to plug and play components and will be plugged in on demand.
    XME_CORE_NODEMGR_COMPREP_STATE_CREATED = 3 ///< Component is announced and has been created, which means it is initialized and registered in the broker.
};

/**
 * \typedef xme_core_nodeMgr_compRep_state_t
 *
 * \brief Possible states of a component. For values see xme_core_nodeMgr_compRep_state_e.
 */
typedef int8_t
xme_core_nodeMgr_compRep_state_t;

/******************************************************************************/
/***   Prototypes                                                           ***/
/******************************************************************************/
XME_EXTERN_C_BEGIN

/**
 * \brief Initializes the component repository.
 *
 * \retval XME_STATUS_SUCCESS if the initialization was successful.
 */
xme_status_t
xme_core_nodeMgr_compRep_init(void);

/**
 * \brief Frees all resources occupied by component repository.
 */
void
xme_core_nodeMgr_compRep_fini(void);

/**
 * \brief Get the handle for the specified component.
 *
 * \param[in] nodeID The node ID of the component's node.
 *            XME_CORE_NODE_LOCAL_NODE_ID will match itself and
 *            the current value of xme_core_node_getCurrentNodeId().
 * \param[in] componentID The component ID of the component.
 * \param[out] outComponentHandle Resulting handle will be written here.
 *             Only valid when XME_STATUS_SUCCESS is returned.
 *             Must not be NULL.
 *
 * \retval XME_STATUS_SUCCESS if operation was successful.
 * \retval XME_STATUS_INVALID_PARAMETER if outComponentHandle is NULL.
 * \retval XME_STATUS_NOT_FOUND if the specified component was not found
 *         in the repository.
 */
xme_status_t
xme_core_nodeMgr_compRep_getComponentInstance
(
    xme_core_node_nodeId_t nodeID,
    xme_core_component_t componentID,
    xme_core_nodeMgr_compRep_componentHandle_t* const outComponentHandle
);

/**
 * \brief Get the handle of the component which contains the given port.
 *
 * \param[in] portHandle Handle of the port. Must be valid.
 *
 * \return The component handle, or XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE
 *         when the given port handle was invalid or is unknown.
 */
xme_core_nodeMgr_compRep_componentHandle_t
xme_core_nodeMgr_compRep_getComponentInstanceOfPort
(
    xme_core_nodeMgr_compRep_portHandle_t portHandle
);

/**
 * \brief Get the handle of the component which contains the given function.
 *
 * \param[in] functionHandle Handle of the function. Must be valid.
 *
 * \return The component handle, or XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE
 *         when the given function handle was invalid or is unknown.
 */
xme_core_nodeMgr_compRep_componentHandle_t
xme_core_nodeMgr_compRep_getComponentInstanceOfFunction
(
    xme_core_nodeMgr_compRep_functionHandle_t functionHandle
);

/**
 * \brief Initialize the component iterator.
 *
 * \details This iterator allows you to iterate over the handles of all
 *          component instances in the repository.
 *
 * \note The iterations will include components with state
 *       XME_CORE_NODEMGR_COMPREP_STATE_PREPARED.
 *
 * \note The component repository only contains a single iterator.
 */
void
xme_core_nodeMgr_compRep_componentIteratorInit(void);

/**
 * \brief Checks whether the iterator has a next component handle.
 *
 * \return Returns true when the iterator has a next component handle,
 *         false otherwise
 */
bool
xme_core_nodeMgr_compRep_componentIteratorHasNext(void);

/**
 * \brief Returns the next component handle in the iterator.
 *
 * \details Before calling this check first if the iterator has a
 *          next handle.
 *
 * \return The next component handle, if the iterator has a next
 *         handle.
 */
xme_core_nodeMgr_compRep_componentHandle_t
xme_core_nodeMgr_compRep_componentIteratorNext(void);

/**
 * \brief Finalizes the component iterator.
 */
void
xme_core_nodeMgr_compRep_componentIteratorFini(void);

/**
 * \brief Returns the node ID associated to the given component.
 *
 * \param[in] componentHandle Given component handle.
 *
 * \return The node ID, or XME_CORE_NODE_INVALID_NODE_ID when
 *         the given component handle is invalid or unknown.
 */
xme_core_node_nodeId_t
xme_core_nodeMgr_compRep_getNodeID
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle
);

/**
 * \brief Returns the component ID of the given component.
 *
 * \param[in] componentHandle Given component handle.
 *
 * \return The component ID, or XME_CORE_COMPONENT_INVALID_COMPONENT_CONTEXT
 *         when the given component handle is invalid or unknown.
 */
xme_core_component_t
xme_core_nodeMgr_compRep_getComponentID
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle
);

/**
 * \brief Returns the component type of the given component.
 *
 * \param[in] componentHandle Given component handle.
 *
 * \return The component type, or XME_CORE_COMPONENT_TYPE_INVALID
 *         when the given component handle is invalid or unknown.
 */
xme_core_componentType_t
xme_core_nodeMgr_compRep_getComponentType
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle
);

/**
 * \brief Returns the initialization string of the given component.
 *
 * \param[in] componentHandle Given component handle.
 *
 * \return Pointer to the initialization string, or NULL when
 *         the given component handle is invalid or unknown.
 */
const char*
xme_core_nodeMgr_compRep_getInitializationString
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle
);

/**
 * \brief Returns the current state of the given component.
 *
 * \param[in] componentHandle Given component handle.
 *
 * \return The state, or XME_CORE_NODEMGR_COMPREP_STATE_INVALID when
 *         the given component handle is invalid or unknown.
 */
xme_core_nodeMgr_compRep_state_t
xme_core_nodeMgr_compRep_getState
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle
);

/**
 * \brief Get the handle of a port contained in the given component.
 *
 * \param[in] componentHandle Given component handle.
 * \param[in] portTypeID Index of the port, as defined in the component manifest.
 *
 * \return The port handle, or XME_CORE_NODEMGR_COMPREP_INVALID_HANDLE when
 *         the given component handle is invalid, unknown or when the
 *         portTypeID is invalid for the given component.
 */
xme_core_nodeMgr_compRep_portHandle_t
xme_core_nodeMgr_compRep_getPort
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle,
    uint16_t portTypeID
);

/**
 * \brief Returns the data packet ID of the given port.
 *
 * \note This is only available when the port is located on the
 *       local node and the component has already been created.
 *
 * \param[in] portHandle Given port handle.
 *
 * \return The data packet ID, or XME_CORE_DATAMANAGER_DATAPACKETID_INVALID
 *         when the given port handle is invalid or unknown, or the port
 *         is not created or not local.
 */
xme_core_dataManager_dataPacketId_t
xme_core_nodeMgr_compRep_getDataPacketID
(
    xme_core_nodeMgr_compRep_portHandle_t portHandle
);

/**
 * \brief Returns the queue size of the given port.
 *
 * \param[in] portHandle Given port handle.
 *
 * \return The queue size, or 0 when the given port handle is invalid
 *         or unknown.
 */
uint16_t
xme_core_nodeMgr_compRep_getQueueSize
(
    xme_core_nodeMgr_compRep_portHandle_t portHandle
);

/**
 * \brief Get the handle of a function contained in the given component.
 *
 * \param[in] componentHandle Given component handle.
 * \param[in] functionTypeID Index of the function, as defined in the component manifest.
 *
 * \return The function handle.
 */
xme_core_nodeMgr_compRep_functionHandle_t
xme_core_nodeMgr_compRep_getFunction
(
    xme_core_nodeMgr_compRep_componentHandle_t componentHandle,
    uint16_t functionTypeID
);

/**
 * \brief Get the execution period of the given function.
 *
 * \param[in] functionHandle Given function handle.
 *
 * \return The execution period, or 0 when the given
 *         function handle is invalid or unknown. Note that
 *         0 may also a valid execution period.
 */
xme_hal_time_timeInterval_t
xme_core_nodeMgr_compRep_getExecutionPeriod
(
    xme_core_nodeMgr_compRep_functionHandle_t functionHandle
);

/**
 * \brief Returns the descriptor of the given function.
 *
 * \note This is only available when the port is located on the
 *       local node and the component has already been created.
 *
 * \param[in] functionHandle Given function handle.
 *
 * \return Pointer to the function descriptor, or NULL when
 *         the given function handle is invalid, unkown, or
 *         when the function is not created yet or not local.
 */
const xme_core_exec_functionDescriptor_t*
xme_core_nodeMgr_compRep_getFunctionDescriptor
(
    xme_core_nodeMgr_compRep_functionHandle_t functionHandle
);

XME_EXTERN_C_END

/**
 * @}
 */

#endif // #ifndef XME_CORE_NODEMGR_COMPONENTREPOSITORY_H
